const Sqlite = require("./sqlite.cjs");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");

const DB = new Sqlite();
const { checkAccount } = "./share.cjs";

const tableName = "personInfo";
const auth_allow = ["/api/login", "/auth_allow/xxx"];
const SECRET_KEY = "xxinfairsn@asin34ai_SRTin";

let meg;
let ok;

const login = async (user) => {
  let userinfo = {};
  meg = "unknow error";
  try {
    // 0. check required fields
    if (!(user && user.account && user.password)) {
      //throw new Error("invailed parameters!  name or password is empty!");
      meg = "name or password is empty!";
      throw new Error(meg);
    }
    // 1.get user info
    const users = await DB.queryTable({
      tableName: tableName + "_data",
      where: "textInput101 = ?",
      params: [user.account],
    });
    //console.log(users);
    if (users.length !== 1) {
      meg = "account not found.";
      throw new Error(meg);
    }
    // 2.compare paassword
    const encrypted = users[0].textInput102;
    //console.log(encrypted);
    ok = bcrypt.compareSync(user.password, encrypted);
    //console.log("ok:", ok);
    if (!ok) {
      meg = "password not match.";
      throw new Error(meg);
    }
    meg = "login success";
    // attach users info (user dataMap, make data more readable)
    const tableInfo = await DB.queryTable({ tableName: tableName });
    userinfo = DB.tableDataMap(users[0], tableInfo);
  } catch (e) {
    ok = false;
    console.log(meg);
  } finally {
    return {
      message: meg,
      ok: ok,
      user: userinfo,
    };
  }
};

const register = async (user) => {
  try {
    console.log(user);
    // 0. check required fields
    if (!(user && user.name && user.password)) {
      throw "invailed parameters!  name or password is empty!";
    }
    // 1. check user's account is valid, here is phone number
    if (!checkAccount(user.account)) {
      throw "account is not vaild!";
    }
    // 2. check user's account is exists?
    const users = await DB.queryTable({
      tableName: tableName + "_data",
      where: "textInput101 = ?",
      params: [user.account],
    });
    // const usersAll = await DB.queryTable({
    //   tableName: "personInfo_data",
    // });
    // //console.log(`usersAll is:`, ...usersAll);
    //console.log(`users is:`, ...users);
    if (users.length > 0) {
      throw "account has exists";
    }
    // 3. create new user
    await DB.insertManyData({
      tableName: tableName + "_data",
      //          name,      account,      password,      identity
      schemas: [
        //ruquired
        "textInput100", //name  ,    true
        "textInput101", //account     true
        "textInput102", //password true
        "numberInput103", //phone
        "select104", //identity
      ],
      data: [
        {
          textInput100: user.name,
          textInput101: user.account,
          textInput102: user.password,
          textInput103: user.phone,
          select104: "user", //this is default normal user
        },
      ],
    });
    meg = `user ${user.name} register succuss.`;
    ok = true;
  } catch (e) {
    console.log(e);
    console.error("register: [failed to register new user.]");
    meg = e;
    ok = false;
  } finally {
    return {
      message: meg,
      ok: ok,
    };
  }
};
//
//
// const run = async () => {
//   const user = {
//     name: "h",
//     password: "h",
//     account: "17112345678",
//   };
//   // meg = await register(user);
//   // console.log(meg);
//   //  return;
//   meg = await login(user);
//   console.log(meg);
// };
//run();
const sign = (result) =>
  jwt.sign(result.user, SECRET_KEY, { expiresIn: "10d" });

const auth = async (req, res, next) => {
  if (req.method === "OPTIONS") {
    return res.status(200).end();
  }
  //
  for (let url of auth_allow) {
    if (url === req.originalUrl) {
      console.log("enter login.");
      return next();
    }
  }
  //console.log(`auth:`, req.method);
  try {
    //console.log("enter try");
    // check token
    const raw = req.headers.authorization;
    const token = String(raw).split(" ")[1];
    if (!token) {
      throw new Error("Unauthorized");
    }
    jwt.verify(token, SECRET_KEY, (err, user) => {
      if (err) {
        throw new Error("token auth failed");
      }
      // ok, get user info
      req.user = user;
      next();
    });
  } catch (e) {
    // auth failed, into login page
    // console.log(e);
    //proxy.web(req, res, { target: webLoginPage });
    //res.redirect(webLoginPage);
    //console.log(e);
    //console.log("please login, Unauthorized  ");
    // console.log(req);
    // console.log(req.headers);
    console.log(e.message);
    res.status(300).json({ message: e.message });
    //res.redirect(webLoginPage);
    //res.send(resWebogin.data);
    //console.log("after  please login, ready redirect ");
    //return;
  }
};

module.exports = {
  auth,
  login,
  register,
  sign,
};
